#ifndef __LCD_H__
#define __LCD_H__

#include <stdint.h>

#define USE_LCD1602    (1)
#define USE_LCD12864   (0)
#define LCD_DATA_BITS  (8)

#if USE_LCD1602
#define LCD_ROWS (2)
#define LCD_COLS (16)
#endif

#if USE_LCD12864
#define LCD_ROWS (64)
#define LCD_COLS (128)
#endif

/*******************************
 *         硬件抽象层(HAL)
 ******************************/
// 引脚类型定义
typedef struct {
    void (*set_output)(void);    // 设置为输出模式
    void (*set_high)(int);      // 输出高电平
    void (*set_low)(int);       // 输出低电平
} GPIO_TypeDef;

// 延时函数指针类型
typedef void (*delay_func)(uint32_t ms);

// LCD配置结构体
typedef struct {
    // 控制线
    GPIO_TypeDef RS;
    GPIO_TypeDef RW;
    GPIO_TypeDef EN;
    
    // 数据线（支持4/8位模式）
    GPIO_TypeDef DATA[8];
    
    // 延时函数
    delay_func delay_ms;
    delay_func delay_us;
    
    // 工作模式
    uint8_t data_bits;  // 4 or 8
    uint8_t display_lines; // 1 or 2

    // 尺寸
    uint8_t width;
    uint8_t height;
} LCD_ConfigTypeDef;

/*******************************
 *         应用层(APL)
 ******************************/
// LCD操作句柄
typedef struct {
    LCD_ConfigTypeDef config;
    uint8_t display_control;
    uint8_t entry_mode;
    uint8_t cursor_row;
    uint8_t cursor_col;
} LCD_HandleTypeDef;

// LCD命令定义
typedef enum {
    LCD_CMD_CLEAR        = 0x01,
    LCD_CMD_HOME         = 0x02,
    LCD_CMD_ENTRY_MODE   = 0x04,
    LCD_CMD_DISPLAY_CTRL = 0x08,
    LCD_CMD_SHIFT        = 0x10,
    LCD_CMD_FUNCTION_SET = 0x20,
    LCD_CMD_CGRAM_ADDR   = 0x40,
    LCD_CMD_DDRAM_ADDR   = 0x80
} LCD_CommandTypeDef;

// 错误码定义
typedef enum {
    LCD_OK,
    LCD_ERR_INIT,
    LCD_ERR_PARAM,
    LCD_ERR_TIMEOUT
} LCD_Error;

// API接口
LCD_Error LCD_Init(LCD_HandleTypeDef *hlcd, LCD_ConfigTypeDef *config);
LCD_Error LCD_Clear(LCD_HandleTypeDef *hlcd);
LCD_Error LCD_SetCursor(LCD_HandleTypeDef *hlcd, uint8_t row, uint8_t col);
LCD_Error LCD_Print(LCD_HandleTypeDef *hlcd, const char *str);
LCD_Error LCD_Printf(LCD_HandleTypeDef *hlcd, uint8_t row, uint8_t col, const char *fmt, ...);
LCD_Error LCD_DisplayOn(LCD_HandleTypeDef *hlcd);

#endif // __LCD_H__